package com.sb.net;

import com.sb.crawler.impl.ZheJiangZW;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

public class Client {
    private  final Logger logger= LoggerFactory.getLogger(Client.class);

    private OkHttpClient client;

    public Client() {
        client = new OkHttpClient.Builder()
                .cookieJar(new CookieJar() {
                    Map<String, List<Cookie>> cookieMap = new HashMap<>();

                    @Override
                    public void saveFromResponse(HttpUrl httpUrl, List<Cookie> list) {
                        List<Cookie> cookieList = cookieMap.get(getHostPart(httpUrl.host()));
                        if (cookieList == null) {
                            cookieList = new ArrayList<>();
                        }
                        for (int i = 0; i < list.size(); i++) {
                            for (int j = 0; j < cookieList.size(); j++) {
                                if (cookieList.get(j).name().equals(list.get(i).name())) {
                                    cookieList.remove(j);
                                }
                            }
                        }
                        cookieList.addAll(list);
                        cookieMap.put(getHostPart(httpUrl.host()), cookieList);
                    }

                    @Override
                    public List<Cookie> loadForRequest(HttpUrl httpUrl) {
                        return cookieMap.get(getHostPart(httpUrl.host())) == null ? new ArrayList<>() : cookieMap.get(getHostPart(httpUrl.host()));
                    }

                    public String getHostPart(String str) {
                        String[] splits = str.split("\\.");
                        if (splits.length != 3) {
                            return str;
                        } else {
                            return splits[1] + "." + splits[2];
                        }
                    }

                    public String getCookie() {
                        return "";
                    }
                })
                .sslSocketFactory(TrustAllCerts.createSSLSocketFactory())
                .hostnameVerifier(new TrustAllCerts.TrustAllHostnameVerifier())
                .connectTimeout(130, TimeUnit.SECONDS)
                .readTimeout(130, TimeUnit.SECONDS)
                .writeTimeout(130, TimeUnit.SECONDS)
//                .proxy(new Proxy(Proxy.Type.HTTP,new InetSocketAddress("47.94.100.76", 3128)))
//                .addNetworkInterceptor(chain -> {
//                    System.out.println("----------intercept log start----------");
//                    Request request = chain.request();
//                    System.out.println("request headers");
//                    System.out.println(request.url().host());
//                    for (String name : request.headers().names()) {
//                        for (String header : request.headers(name)) {
//                            System.out.println(name + ":" + header);
//                        }
//                    }
//                    System.out.println();
//                    Response response = chain.proceed(request);
//                    System.out.println("response headers" + response.code());
//                    for (String name : response.headers().names()) {
//                        for (String head : response.headers(name)) {
//                            System.out.println(name + ":" + head);
//                        }
//                    }
//                    System.out.println("----------intercept log end-----------");
//                    return response;
//                })
                .addInterceptor(chain -> {
                    return chain.proceed(chain.request().newBuilder()
                            .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36")
                            .build()

                    );
                })
                .build();
    }

    public OkHttpClient init() {
        if (client == null) {
            synchronized (Client.class) {
                if (client == null) {
                    new Client();
                }
            }
        }
        return client;
    }

    public String doGetRequest(String url, Map<String, String> header) {
        Request.Builder builder = new Request.Builder();
        builder.get().url(url);
        if (header != null && header.size() > 0) {
            for (Map.Entry<String, String> entry : header.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue());
            }
        }

        return this.request(builder.build());
    }

    public byte[] doGetRequestImage(String url, Map<String, String> header) {
        Request.Builder builder = new Request.Builder();
        builder.get().url(url);
        if (header != null && header.size() > 0) {
            for (Map.Entry<String, String> entry : header.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue());
            }
        }
        return this.request1(builder.build());
    }

    public String doPostRequest(String url, String postDate, Map<String, String> header) {
        Request.Builder builder = new Request.Builder();
        builder.post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded"), postDate))
                .url(url);
        if (header != null && header.size() > 0) {
            for (Map.Entry<String, String> entry : header.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue());
            }
        }
        return this.request(builder.build());
    }

    private String request(Request request) {
        String responseStr = null;
        try {

            Response response = client.newCall(request).execute();
            int code = response.code();
            responseStr = response.body().string();
            if (code == 200) {
//                logger.info("请求成功");
            } else {
                logger.info("请求失败", "code:" + response.code());
                responseStr = "";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //L.i("responseStr", responseStr);
        return responseStr;
    }

    public byte[] request1(Request request) {
        byte[] responseStr = null;
        try {
            Response response = client.newCall(request).execute();
//            response.body().bytes()
            responseStr = response.body().bytes();
            int code = response.code();
            if (code == 200) {
//                logger.info("请求成功");
            } else {
                logger.info("请求失败", "code:" + response.code());
                responseStr = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return responseStr;
    }

    public void setCookie(Cookie cookie, String Domain) {
        CookieJar cookieJar = client.cookieJar();
        Class<? extends CookieJar> clazz = cookieJar.getClass();
        Field[] fs = clazz.getDeclaredFields();
        for (int i = 0; i < fs.length; i++) {
            Field f = fs[i];
            f.setAccessible(true);
            Object val = null;
            try {
                val = f.get(cookieJar);
            } catch (IllegalAccessException e) {
                logger.info("cookie is null");
            }
            String type = f.getType().toString();
            if (type.endsWith("java.util.Map")) {
                Map<String, List<Cookie>> maps = (Map<String, List<Cookie>>) val;
                List<Cookie> cookies = maps.get(Domain);
                cookies.add(cookie);
            }
        }
    }

    public String getCookie() {
        StringBuffer sb = new StringBuffer();
        CookieJar cookieJar = client.cookieJar();
        Class<? extends CookieJar> clazz = cookieJar.getClass();
        Field[] fs = clazz.getDeclaredFields();
        for (int i = 0; i < fs.length; i++) {
            Field f = fs[i];
            f.setAccessible(true); //设置些属性是可以访问的
            Object val = null;//得到此属性的值
            try {
                val = f.get(cookieJar);
            } catch (IllegalAccessException e) {
                logger.info("cookie is null");
            }
//            System.out.println("name:"+f.getName()+"\t value = "+val);
            String type = f.getType().toString();//得到此属性的类型
            if (type.endsWith("java.util.Map")) {
                Map<String, List<Cookie>> maps = (Map<String, List<Cookie>>) val;
                for (List<Cookie> s : maps.values()) {
                    for (Cookie cookie : s) {
                        if ("_tmp_ck_0".equals(cookie.name()))
                            sb.append(cookie.name()).append("=").append(cookie.value()).append("");
                    }
                }
            }
        }
        logger.info("cookie:" + sb.toString());
        return sb.toString();
    }
}
